ATOM Documentation

← Back to App

Accessibility Manual Testing Checklist

**Purpose:** Covers 60-70% of accessibility issues not caught by automated tools like axe-core.

**When to use:**

  • Before major releases
  • For UI changes in pull requests
  • Quarterly accessibility audits
  • When adding new components or features

**Automated vs Manual Testing:**

  • **Automated (40%):** @axe-core/playwright, jest-axe - detects ARIA issues, missing labels, role problems
  • **Manual (60%):** This checklist - keyboard navigation, screen readers, semantic HTML, mobile, edge cases

---

1. Keyboard Navigation

Automated tools cannot verify if keyboard navigation actually works or makes sense. Only manual testing can confirm:

1.1 Tab Order

  • [ ] **Tab moves focus in logical order** (left-to-right, top-to-bottom)
  • Test: Press Tab repeatedly through the page
  • Expected: Focus follows visual reading order (not source code order)
  • Common issues: Skip links appear, focus jumps to hidden elements
  • [ ] **All interactive elements receive focus**
  • Test: Tab through all buttons, links, inputs, dropdowns
  • Expected: Every interactive element shows a visible focus indicator
  • Common issues: Custom widgets don't accept focus, tabindex misuse
  • [ ] **Focus indicator is visible** (2px solid, 3:1 contrast)
  • Test: Tab to any element and look for the focus ring
  • Expected: Clear outline or background change (WCAG 2.4.7: Focus Visible)
  • Common issues: outline: none without replacement, low contrast focus
  • [ ] **Tab skips hidden/disabled elements**
  • Test: Verify hidden content and disabled form fields are skipped
  • Expected: Tab moves to next visible/interactive element
  • Common issues: tabindex="0" on hidden elements traps focus

1.2 Keyboard Activation

  • [ ] **Enter activates buttons and links**
  • Test: Focus button/link, press Enter
  • Expected: Same action as click/tap
  • Common issues: Custom handlers only respond to mouse events
  • [ ] **Space activates buttons and checkboxes**
  • Test: Focus button/checkbox, press Space
  • Expected: Buttons click, checkboxes toggle (WCAG 2.1.1: Keyboard)
  • Common issues: Space key not handled in custom components
  • [ ] **Arrow keys navigate dropdowns and menus**
  • Test: Open a custom dropdown, use arrow keys
  • Expected: Focus moves through options, up/down arrows work
  • Common issues: Arrow keys ignored, focus doesn't move
  • [ ] **Escape closes modals and cancels actions**
  • Test: Open a modal/dialog, press Escape
  • Expected: Modal closes, focus returns to trigger element
  • Common issues: Escape doesn't work, focus trapped incorrectly

1.3 Focus Trapping

  • [ ] **Modals trap focus** (Tab cycles within modal)
  • Test: Open modal, press Tab repeatedly
  • Expected: Focus cycles through modal content, doesn't reach page behind
  • Common issues: Focus escapes behind modal, can't close with keyboard
  • [ ] **Focus returns to triggering element after modal closes**
  • Test: Open modal, close it (Escape or button)
  • Expected: Focus is on the button that opened the modal
  • Common issues: Focus lost, returns to top of page
  • [ ] **Drawers/sidebars trap focus when open**
  • Test: Open sidebar, press Tab
  • Expected: Focus cycles within sidebar, doesn't reach main content
  • Common issues: Focus escapes, can't access sidebar content
  • [ ] **Skip navigation link visible on focus**
  • Test: Tab from very top of page (before any content)
  • Expected: "Skip to main content" link appears on first Tab
  • Common issues: Skip link hidden off-screen, never receives focus
  • [ ] **Skip link jumps to main content**
  • Test: Activate skip link (press Enter)
  • Expected: Focus moves to <main> or id="main"
  • Common issues: Link goes to wrong element, focus not set
  • [ ] **Multiple skip links for nav/main/footer**
  • Test: Tab through page, look for multiple skip options
  • Expected: Skip links for navigation, main content, footer
  • Common issues: Only one skip link, doesn't help with complex layouts

---

2. Screen Reader Compatibility

Screen readers reveal the accessibility tree that automated tools scan. Only human testing confirms it's usable.

2.1 NVDA (Windows) - Free

  • [ ] **Page title announced on load**
  • Test: Open page, listen to announcement
  • Expected: NVDA says title like "ATUM SaaS - Agent Dashboard"
  • Common issues: Generic titles like "Page" or "Home"
  • [ ] **Landmarks announced** (banner, nav, main, footer)
  • Test: Press NVDA + D (landmarks list)
  • Expected: Navigation landmarks appear (banner, navigation, main, contentinfo)
  • Common issues: No landmarks, all content in one region
  • [ ] **Headings hierarchy (h1 > h2 > h3) is logical**
  • Test: Press H (next heading), Shift+H (previous heading)
  • Expected: Single h1, heading levels not skipped
  • Common issues: Multiple h1, h1 followed by h4, no headings
  • [ ] **Form labels announced with input fields**
  • Test: Navigate to form field with arrows
  • Expected: NVDA says "Email, edit" or "Password, edit, required"
  • Common issues: Unlabeled inputs read as "edit blank", placeholders as labels
  • [ ] **Error messages announced after validation**
  • Test: Submit invalid form, listen for feedback
  • Expected: "Invalid email" or error message read immediately
  • Common issues: Errors not announced, only shown visually (red text)
  • [ ] **Dynamic content updates are announced** (aria-live)
  • Test: Trigger page update (load more, filter change)
  • Expected: NVDA announces "Loading more items" or "5 results found"
  • Common issues: Silent updates, user doesn't know content changed

2.2 VoiceOver (macOS) - Built-in

  • [ ] **Navigate by headings** (VO + H)
  • Test: Press VO + H to jump between headings
  • Expected: Move through h1, h2, h3 in order
  • Common issues: Headings not announced, jumps randomly
  • [ ] **Navigate by landmarks** (VO + U)
  • Test: Press VO + U, select landmark from rotor
  • Expected: List of landmarks appears (banner, nav, main, footer)
  • Common issues: Landmarks missing, rotor shows nothing
  • [ ] **Form controls announced correctly**
  • Test: Navigate to form field (VO + arrow keys)
  • Expected: "Email, edit text" or "Subscribe, checkbox, unchecked"
  • Common issues: Role not announced (just "button"), state unclear
  • [ ] **Focus announcements are accurate**
  • Test: Tab through page, listen to focus changes
  • Expected: Every focus change is announced with element name/role
  • Common issues: Silent focus, "unknown" announced

2.3 Screen Reader Testing Tips

**Don't test everything:**

  • Focus on user flows (login, agent creation, billing)
  • Test complex components (modals, dropdowns, data tables)
  • Verify dynamic content (search results, filtered lists)

**Use shortcuts:**

  • NVDA: H (heading), F (form field), L (list), B (button)
  • VoiceOver: VO + U (landmarks), VO + H (headings), VO + I (items)

---

3. Semantic HTML

Automated tools check for semantic tags, but only humans verify the tags make semantic sense.

3.1 Landmarks

  • [ ] **<header> for site header**
  • Test: View source, search for <header>
  • Expected: Top navigation/banner in <header> with role="banner"
  • Common issues: <div class="header"> instead of semantic tag
  • [ ] **<nav> for navigation**
  • Test: View source, find navigation areas
  • Expected: Main nav, footer nav in <nav> with role="navigation"
  • Common issues: Navigation in <div>, no landmarks announced
  • [ ] **<main> for main content**
  • Test: View source, search for <main>
  • Expected: Page content in <main> with role="main"
  • Common issues: Content in <div id="main">, no main landmark
  • [ ] **<footer> for footer**
  • Test: View source, find footer area
  • Expected: Site footer in <footer> with role="contentinfo"
  • Common issues: Footer in <div class="footer">
  • [ ] **<aside> for sidebar content**
  • Test: View source, find sidebars/panels
  • Expected: Related content in <aside> with role="complementary"
  • Common issues: Sidebars in <div>, not semantically related

3.2 Headings

  • [ ] **Single h1 per page**
  • Test: View source, count <h1> tags
  • Expected: Exactly one <h1> per page
  • Common issues: Multiple h1 for logo/title/content
  • [ ] **Heading levels not skipped**
  • Test: View source, check heading sequence
  • Expected: h1 → h2 → h3 (no h1 → h4 jumps)
  • Common issues: h1 followed by h3 or h4 for styling
  • [ ] **Headings describe content sections**
  • Test: Read headings out of context
  • Expected: Headings make sense without page content
  • Common issues: Generic headings like "Section 1" or "Info"

3.3 Lists

  • [ ] **Related items use <ul> or <ol>**
  • Test: View source, find groups of related items
  • Expected: Navigation menus, bullet points in list markup
  • Common issues: Lists made of <div> elements
  • [ ] **Navigation menus use list markup**
  • Test: Inspect nav menu, view source
  • Expected: <nav><ul><li><a>... structure
  • Common issues: Navigation links in <span> or <div>

3.4 Forms

  • [ ] **All inputs have associated labels**
  • Test: Click label text, does input get focus?
  • Expected: Clicking label focuses the input (implicit/explicit association)
  • Common issues: Labels not connected via for attribute or nesting
  • [ ] **Required fields indicated with aria-required**
  • Test: Inspect required input, check attributes
  • Expected: aria-required="true" or required attribute
  • Common issues: Required only shown visually (asterisk, red border)
  • [ ] **Error messages linked with aria-describedby**
  • Test: Trigger error, inspect input and error message
  • Expected: aria-describedby="error-id" connects input to error
  • Common issues: Errors not linked to inputs programmatically
  • [ ] **Field validation announced**
  • Test: Submit invalid form with screen reader
  • Expected: "3 errors, first error in Email field"
  • Common issues: Errors shown visually but not announced

---

4. Mobile Accessibility

Automated tools can't test touch interactions or mobile behavior.

4.1 Touch Targets

  • [ ] **Interactive elements ≥ 44x44 CSS pixels**
  • Test: Open DevTools, measure button/link dimensions
  • Expected: Width and height both ≥ 44px (WCAG 2.5.5: Target Size)
  • Common issues: Small buttons (< 40px), inline links too close
  • [ ] **Touch targets have spacing between them**
  • Test: Tap adjacent buttons, do they activate separately?
  • Expected: 8px+ spacing between targets (iOS/android guideline)
  • Common issues: Buttons touching, mis-taps common
  • [ ] **No mouse-only interactions** (hover menus)
  • Test: Try to navigate without hover (finger/touch)
  • Expected: All content accessible without hover
  • Common issues: Dropdowns only open on hover, no tap alternative

4.2 Orientation

  • [ ] **Content usable in portrait and landscape**
  • Test: Rotate device or resize browser to mobile width
  • Expected: No horizontal scroll, content adapts to orientation
  • Common issues: Landscape mode breaks, horizontal scroll required
  • [ ] **No orientation lock required**
  • Test: Rotate device, does content reflow?
  • Expected: Works in both portrait and landscape
  • Common issues: "Rotate your device" message, forces one orientation

4.3 Zoom

  • [ ] **Content zooms to 200% without horizontal scroll**
  • Test: Browser zoom to 200% (Cmd/Ctrl +)
  • Expected: No horizontal scroll, text reflows (WCAG 1.4.10: Reflow)
  • Common issues: Fixed-width containers, horizontal scroll at 200%
  • [ ] **Text reflows when zoomed**
  • Test: Browser zoom to 200%, check layout
  • Expected: Text wraps, columns stack, no content cut off
  • Common issues: Two-column layout breaks at 200% zoom
  • [ ] **No pinch-zoom required** (viewport meta tag)
  • Test: Check viewport meta tag in source
  • Expected: <meta name="viewport" content="width=device-width, initial-scale=1">
  • Common issues: user-scalable=no prevents zoom (WCAG violation)

4.4 Responsive

  • [ ] **Layout adapts to different screen sizes**
  • Test: Resize browser from desktop to mobile width
  • Expected: Layout transitions smoothly, no content overlap
  • Common issues: Breakpoints break, content overlaps at certain widths
  • [ ] **Touch targets remain accessible on mobile**
  • Test: Check button/link sizes on mobile viewport
  • Expected: All interactive elements ≥ 44x44px
  • Common issues: Desktop-sized buttons, links too small on mobile

---

5. Edge Cases (Not Caught by Automated Tools)

Automated tools scan the DOM, but they can't verify behavior over time or complex interactions.

5.1 Dynamic Content

  • [ ] **Page changes announced with aria-live regions**
  • Test: Trigger dynamic update (search, filter, async load)
  • Expected: Screen reader announces change ("5 results found")
  • Common issues: Silent updates, user doesn't know page changed
  • [ ] **Loading states are announced**
  • Test: Submit form that loads data
  • Expected: "Loading..." or spinner announced (not visible)
  • Common issues: Loading only visible (spinner), not announced
  • [ ] **Modal open/close announced**
  • Test: Open modal with screen reader
  • Expected: "Dialog opened" or role="dialog" announced
  • Common issues: Modal opens silently, screen reader still reading background

5.2 Custom Components

  • [ ] **Custom dropdowns have proper ARIA roles**
  • Test: Inspect custom dropdown element
  • Expected: role="combobox", aria-expanded, aria-haspopup
  • Common issues: Custom widget looks like dropdown but acts like div
  • [ ] **Custom checkboxes implement aria-checked**
  • Test: Inspect custom checkbox/toggle
  • Expected: role="checkbox", aria-checked="true/false"
  • Common issues: Visual toggle not exposed as checkbox to screen readers
  • [ ] **Custom sliders implement aria-valuenow/min/max**
  • Test: Inspect custom range slider
  • Expected: role="slider", aria-valuenow, aria-valuemin, aria-valuemax
  • Common issues: Slider value not exposed, "unknown" announced

5.3 Drag and Drop

  • [ ] **Keyboard alternative provided**
  • Test: Try to reorder items without mouse
  • Expected: Arrow keys or alternative method to reorder
  • Common issues: Drag-and-drop only, no keyboard option
  • [ ] **Instructions are visible/announced**
  • Test: Check if drag-and-drop instructions are readable
  • Expected: "Drag to reorder" or similar instructions visible/announced
  • Common issues: Drag-and-drop area has no instructions

5.4 Time-Based Media

  • [ ] **Auto-playing content can be paused**
  • Test: Find auto-playing video/carousel
  • Expected: Pause/stop button available and accessible
  • Common issues: Auto-play with no pause control (WCAG 2.2.2: Pause, Stop, Hide)
  • [ ] **Moving content has pause/stop controls**
  • Test: Find auto-scrolling content or animation
  • Expected: Pause button available, motion stops
  • Common issues: Carousels auto-advance without pause

---

6. Images and Media

Automated tools detect missing alt text, but not whether it's meaningful.

6.1 Alt Text

  • [ ] **Informative images have descriptive alt**
  • Test: Inspect informative image (icon, photo, diagram)
  • Expected: alt="User profile picture" or alt="Sales trend chart"
  • Common issues: Generic alt like "image" or "photo"
  • [ ] **Decorative images have alt=""**
  • Test: Find decorative images (spacing, styling)
  • Expected: alt="" or role="presentation"
  • Common issues: Decorative images announced as "image" or filename
  • [ ] **Complex images have long descriptions**
  • Test: Find charts, graphs, complex diagrams
  • Expected: Long description via aria-describedby, longdesc, or adjacent text
  • Common issues: Complex image with brief/missing alt

6.2 Captions

  • [ ] **Videos have synchronized captions**
  • Test: Play video, check for caption track
  • Expected: <track kind="captions"> or captions available
  • Common issues: No captions, auto-generated captions only
  • [ ] **Audio-only content has transcripts**
  • Test: Find audio-only content (podcast, voice note)
  • Expected: Transcript text available on page
  • Common issues: Audio without text alternative

---

7. Error Handling

Automated tools can't verify if error recovery is actually possible.

  • [ ] **Errors announced with aria-live**
  • Test: Trigger error, check if screen reader announces it
  • Expected: Error message announced immediately (aria-live="assertive")
  • Common issues: Errors shown but not announced
  • [ ] **Error messages linked to inputs**
  • Test: Click error text, does input get focus?
  • Expected: Clicking error focuses related input
  • Common issues: Errors not linked, unclear which field has error
  • [ ] **Recovery suggestions provided**
  • Test: Trigger error, read error message
  • Expected: "Invalid email format" or "Password must be 8+ characters"
  • Common issues: "Invalid input" with no guidance
  • [ ] **Form validation doesn't submit with errors**
  • Test: Submit invalid form
  • Expected: Form blocks submission, errors shown
  • Common issues: Invalid data submits, backend errors

---

PR Review Integration

For UI changes in pull requests, reviewers should verify:

**Quick checks (2 minutes):**

  1. **Keyboard navigation**: Tab through, focus indicator visible?
  2. **Focus indicators**: Can you see where you are?
  3. **Screen reader**: Navigate with VO/NVDA, does it make sense?
  4. **Touch targets**: If mobile component, are buttons ≥ 44x44px?

**Full checks (10 minutes):**

  1. Run through relevant sections of this checklist
  2. Test complex components (modals, dropdowns, forms)
  3. Verify dynamic content updates are announced
  4. Check responsive behavior on mobile viewport

**When to skip:**

  • Non-UI changes (backend, infrastructure, documentation)
  • Bug fixes that don't change component structure
  • Minor styling tweaks (unless affecting focus/contrast)

---

Testing Tools

**Screen Readers:**

  • NVDA (Windows, free): https://www.nvaccess.org/
  • VoiceOver (macOS, built-in): Cmd + F5 to enable
  • JAWS (Windows, paid): https://www.freedomscientific.com/

**Keyboard Testing:**

  • Unplug mouse/disable trackpad
  • Use Tab, Enter, Space, Escape, Arrow keys

**Mobile Testing:**

  • Chrome DevTools device emulation (Cmd + Shift + M)
  • Real device testing (iPhone, Android)

**Contrast Checking:**

npm run check:contrast "#FFFFFF" "#000000"

**Automated Scanning:**

npm run test:a11y        # Run axe-core E2E tests
npm run test:a11y:unit   # Run jest-axe component tests

---

References

  • **WCAG 2.1 Guidelines:** https://www.w3.org/WAI/WCAG21/quickref/
  • **ARIA Authoring Practices:** https://www.w3.org/WAI/ARIA/apg/
  • **WebAIM Checklist:** https://webaim.org/standards/wcag/checklist
  • **Accessibility Insights:** https://accessibilityinsights.io/

---

**Last Updated:** 2026-03-22

**Maintained by:** ATOM SaaS Team

**Questions:** Contact the accessibility working group